#pragma once
#include"common.hpp"


const int defbacklog = 6;
using fun_t = std::function<std::string(int sfd,const std::string& buff,Inetaddr& addr)>;


class Tcpserver : public nocopy{

    void Servetask(int sfd,Inetaddr& peer)
    {
        //LOG(level::INFO)<<"INtask";
        char buff[1024];
        while(1)
        {
            ssize_t rs = read(sfd,buff,sizeof(buff)-1);
            if(rs > 0){
                buff[rs] = 0;
                //std::cout<< peer.String_addr() << "say# "<<buff<<std::endl;
                std::string result = _fun(sfd,buff,peer);
                
                write(sfd,result.c_str(),result.size());

            }
            else if (rs == 0)
            {
                LOG(level::INFO) << peer.String_addr() << " 退出了...";
                close(sfd);
                break;
            }
            else
            {
                LOG(level::DEBUG) << peer.String_addr() << " 异常...";
                close(sfd);
                break;
            }
            
            //LOG(level::DEBUG)<<"task success";
        }

    }
public:
    Tcpserver(const uint16_t port,fun_t fun)
    :_port(port),
    _listenfd(-1),
    _fun(fun),
    _Isrunning(false)
    {}

    void Init()
    {
        _listenfd = socket(AF_INET,SOCK_STREAM,0);
        if(_listenfd < 0)
        {
            LOG(level::FATAL)<<"Socket false";
            exit(SOCKER_ERR);
        }
        LOG(level::INFO)<<"socket success "<<_listenfd;
        Inetaddr saddr(_port);
        int n = bind(_listenfd,(const struct sockaddr*)&saddr.Getaddr(),sizeof(saddr.Getaddr()));

        if(n == -1)
        {
            LOG(level::FATAL)<<"bind false";
            exit(BIND_ERR);
        }

        if(listen(_listenfd,defbacklog) < 0)
        {
            LOG(level::FATAL)<<"listen false";
            exit(LISTEN_ERR);
        }
        LOG(level::INFO)<<"Init success";
    }
    
    class ThreadData
    {
        public:
        ThreadData(const int& fd,Inetaddr& addr,Tcpserver* ts)
        :_sfd(fd),
        _addr(addr),
        _ts(ts)
        {}


        ~ThreadData(){}
        
            int _sfd;
            Inetaddr _addr;
            Tcpserver* _ts;
    };

    //这个是线程任务
    static void* Routine(void* argv)
    {
        LOG(level::DEBUG)<<"In Routine";
        //线程分离
        pthread_detach(pthread_self());
        ThreadData* thdata = static_cast<ThreadData*>(argv);
        thdata->_ts->Servetask(thdata->_sfd,thdata->_addr);
        
        return nullptr;
    }

    void Start()
    {
        _Isrunning = true;
        while(_Isrunning)
        {
            struct sockaddr_in peer;
            socklen_t sz = sizeof(peer);
            int sfd = accept(_listenfd,(sockaddr*)&peer,&sz);
            if(sfd < 0)
            {
                LOG(level::ERROR)<<"accept false";
                exit(ACCEPT_ERR);
            }
            LOG(level::DEBUG)<<"accept success "<<sfd;
            Inetaddr local(peer);

            ThreadData* thdata = new ThreadData(sfd,local,this);
            pthread_t th1;
            pthread_create(&th1,nullptr,Routine,thdata);

            // pid_t id = fork();
            // if(id < 0)
            // {
            //     LOG(level::ERROR)<<"fork false";
            //     exit(FORK_ERR);
            // }
            // else if(id == 0)
            // {
            //     close(_listenfd);
            //     if(fork() > 0)
            //         exit(SUCCESS);
            //     //do
            //     Servetask(sfd,local);
            //     //_fun(sfd,local);
            //     exit(SUCCESS);
            // }
            // else
            // {
            //     close(sfd);
            //     pid_t rid = waitpid(id,nullptr,0);
            // }

        }
        _Isrunning = false;

        


    }

    ~Tcpserver(){}

private:
    int _listenfd;
    uint16_t _port;
    bool _Isrunning;
    
    fun_t _fun;
};